home *** CD-ROM | disk | FTP | other *** search
- ; -*- fundamental -*- (asm-mode sucks)
- ; $Id: isolinux.asm,v 1.113 2004/12/30 21:16:04 hpa Exp $
- ; ****************************************************************************
- ;
- ; isolinux.asm
- ;
- ; A program to boot Linux kernels off a CD-ROM using the El Torito
- ; boot standard in "no emulation" mode, making the entire filesystem
- ; available. It is based on the SYSLINUX boot loader for MS-DOS
- ; floppies.
- ;
- ; Copyright (C) 1994-2004 H. Peter Anvin
- ;
- ; This program is free software; you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
- ; Boston MA 02111-1307, USA; either version 2 of the License, or
- ; (at your option) any later version; incorporated herein by reference.
- ;
- ; ****************************************************************************
-
- %define IS_ISOLINUX 1
- %include "macros.inc"
- %include "config.inc"
- %include "kernel.inc"
- %include "bios.inc"
- %include "tracers.inc"
- %include "layout.inc"
-
- ;
- ; Some semi-configurable constants... change on your own risk.
- ;
- my_id equ isolinux_id
- FILENAME_MAX_LG2 equ 8 ; log2(Max filename size Including final null)
- FILENAME_MAX equ (1 << FILENAME_MAX_LG2)
- NULLFILE equ 0 ; Zero byte == null file name
- NULLOFFSET equ 0 ; Position in which to look
- retry_count equ 6 ; How patient are we with the BIOS?
- %assign HIGHMEM_SLOP 128*1024 ; Avoid this much memory near the top
- MAX_OPEN_LG2 equ 6 ; log2(Max number of open files)
- MAX_OPEN equ (1 << MAX_OPEN_LG2)
- SECTOR_SHIFT equ 11 ; 2048 bytes/sector (El Torito requirement)
- SECTOR_SIZE equ (1 << SECTOR_SHIFT)
-
- ;
- ; This is what we need to do when idle
- ;
- %macro RESET_IDLE 0
- ; Nothing
- %endmacro
- %macro DO_IDLE 0
- ; Nothing
- %endmacro
-
- ;
- ; The following structure is used for "virtual kernels"; i.e. LILO-style
- ; option labels. The options we permit here are `kernel' and `append
- ; Since there is no room in the bottom 64K for all of these, we
- ; stick them at vk_seg:0000 and copy them down before we need them.
- ;
- struc vkernel
- vk_vname: resb FILENAME_MAX ; Virtual name **MUST BE FIRST!**
- vk_rname: resb FILENAME_MAX ; Real name
- vk_appendlen: resw 1
- alignb 4
- vk_append: resb max_cmd_len+1 ; Command line
- alignb 4
- vk_end: equ $ ; Should be <= vk_size
- endstruc
-
- ;
- ; Segment assignments in the bottom 640K
- ; 0000h - main code/data segment (and BIOS segment)
- ;
- real_mode_seg equ 3000h
- vk_seg equ 2000h ; Virtual kernels
- xfer_buf_seg equ 1000h ; Bounce buffer for I/O to high mem
- comboot_seg equ real_mode_seg ; COMBOOT image loading zone
-
- ;
- ; File structure. This holds the information for each currently open file.
- ;
- struc open_file_t
- file_sector resd 1 ; Sector pointer (0 = structure free)
- file_left resd 1 ; Number of sectors left
- endstruc
-
- %ifndef DEPEND
- %if (open_file_t_size & (open_file_t_size-1))
- %error "open_file_t is not a power of 2"
- %endif
- %endif
-
- struc dir_t
- dir_lba resd 1 ; Directory start (LBA)
- dir_len resd 1 ; Length in bytes
- dir_clust resd 1 ; Length in clusters
- endstruc
-
- ; ---------------------------------------------------------------------------
- ; BEGIN CODE
- ; ---------------------------------------------------------------------------
-
- ;
- ; Memory below this point is reserved for the BIOS and the MBR
- ;
- section .earlybss
- trackbufsize equ 8192
- trackbuf resb trackbufsize ; Track buffer goes here
- getcbuf resb trackbufsize
- ; ends at 4800h
-
- section .bss
- alignb 4
- ISOFileName resb 64 ; ISO filename canonicalization buffer
- ISOFileNameEnd equ $
- CurDir resb dir_t_size ; Current directory
- RootDir resb dir_t_size ; Root directory
- FirstSecSum resd 1 ; Checksum of bytes 64-2048
- ImageDwords resd 1 ; isolinux.bin size, dwords
- InitStack resd 1 ; Initial stack pointer (SS:SP)
- DiskSys resw 1 ; Last INT 13h call
- ImageSectors resw 1 ; isolinux.bin size, sectors
- DiskError resb 1 ; Error code for disk I/O
- DriveNo resb 1 ; CD-ROM BIOS drive number
- ISOFlags resb 1 ; Flags for ISO directory search
- RetryCount resb 1 ; Used for disk access retries
-
- _spec_start equ $
-
- ;
- ; El Torito spec packet
- ;
-
- alignb 8
- spec_packet: resb 1 ; Size of packet
- sp_media: resb 1 ; Media type
- sp_drive: resb 1 ; Drive number
- sp_controller: resb 1 ; Controller index
- sp_lba: resd 1 ; LBA for emulated disk image
- sp_devspec: resw 1 ; IDE/SCSI information
- sp_buffer: resw 1 ; User-provided buffer
- sp_loadseg: resw 1 ; Load segment
- sp_sectors: resw 1 ; Sector count
- sp_chs: resb 3 ; Simulated CHS geometry
- sp_dummy: resb 1 ; Scratch, safe to overwrite
-
- ;
- ; EBIOS drive parameter packet
- ;
- alignb 8
- drive_params: resw 1 ; Buffer size
- dp_flags: resw 1 ; Information flags
- dp_cyl: resd 1 ; Physical cylinders
- dp_head: resd 1 ; Physical heads
- dp_sec: resd 1 ; Physical sectors/track
- dp_totalsec: resd 2 ; Total sectors
- dp_secsize: resw 1 ; Bytes per sector
- dp_dpte: resd 1 ; Device Parameter Table
- dp_dpi_key: resw 1 ; 0BEDDh if rest valid
- dp_dpi_len: resb 1 ; DPI len
- resb 1
- resw 1
- dp_bus: resb 4 ; Host bus type
- dp_interface: resb 8 ; Interface type
- db_i_path: resd 2 ; Interface path
- db_d_path: resd 2 ; Device path
- resb 1
- db_dpi_csum: resb 1 ; Checksum for DPI info
-
- ;
- ; EBIOS disk address packet
- ;
- alignb 8
- dapa: resw 1 ; Packet size
- .count: resw 1 ; Block count
- .off: resw 1 ; Offset of buffer
- .seg: resw 1 ; Segment of buffer
- .lba: resd 2 ; LBA (LSW, MSW)
-
- ;
- ; Spec packet for disk image emulation
- ;
- alignb 8
- dspec_packet: resb 1 ; Size of packet
- dsp_media: resb 1 ; Media type
- dsp_drive: resb 1 ; Drive number
- dsp_controller: resb 1 ; Controller index
- dsp_lba: resd 1 ; LBA for emulated disk image
- dsp_devspec: resw 1 ; IDE/SCSI information
- dsp_buffer: resw 1 ; User-provided buffer
- dsp_loadseg: resw 1 ; Load segment
- dsp_sectors: resw 1 ; Sector count
- dsp_chs: resb 3 ; Simulated CHS geometry
- dsp_dummy: resb 1 ; Scratch, safe to overwrite
-
- alignb 4
- _spec_end equ $
- _spec_len equ _spec_end - _spec_start
-
- alignb open_file_t_size
- Files resb MAX_OPEN*open_file_t_size
-
- ;
- ; Constants for the xfer_buf_seg
- ;
- ; The xfer_buf_seg is also used to store message file buffers. We
- ; need two trackbuffers (text and graphics), plus a work buffer
- ; for the graphics decompressor.
- ;
- xbs_textbuf equ 0 ; Also hard-coded, do not change
- xbs_vgabuf equ trackbufsize
- xbs_vgatmpbuf equ 2*trackbufsize
-
- section .text
- ;;
- ;; Primary entry point. Because BIOSes are buggy, we only load the first
- ;; CD-ROM sector (2K) of the file, so the number one priority is actually
- ;; loading the rest.
- ;;
- bootsec equ $
-
- StackBuf equ $-44
-
- _start: ; Far jump makes sure we canonicalize the address
- cli
- jmp 0:_start1
- times 8-($-$$) nop ; Pad to file offset 8
-
- ; This table hopefully gets filled in by mkisofs using the
- ; -boot-info-table option. If not, the values in this
- ; table are default values that we can use to get us what
- ; we need, at least under a certain set of assumptions.
- bi_pvd: dd 16 ; LBA of primary volume descriptor
- bi_file: dd 0 ; LBA of boot file
- bi_length: dd 0xdeadbeef ; Length of boot file
- bi_csum: dd 0xdeadbeef ; Checksum of boot file
- bi_reserved: times 10 dd 0xdeadbeef ; Reserved
-
- _start1: mov [cs:InitStack],sp ; Save initial stack pointer
- mov [cs:InitStack+2],ss
- xor ax,ax
- mov ss,ax
- mov sp,StackBuf ; Set up stack
- mov ds,ax
- mov es,ax
- mov fs,ax
- mov gs,ax
- sti
-
- cld
- ; Show signs of life
- mov si,syslinux_banner
- call writestr
- %ifdef DEBUG_MESSAGES
- mov si,copyright_str
- call writestr
- %endif
-
- ;
- ; Before modifying any memory, get the checksum of bytes
- ; 64-2048
- ;
- initial_csum: xor edi,edi
- mov si,_start1
- mov cx,(SECTOR_SIZE-64) >> 2
- .loop: lodsd
- add edi,eax
- loop .loop
- mov [FirstSecSum],edi
-
- mov [DriveNo],dl
- %ifdef DEBUG_MESSAGES
- mov si,startup_msg
- call writemsg
- mov al,dl
- call writehex2
- call crlf
- %endif
- ;
- ; Initialize spec packet buffers
- ;
- mov di,_spec_start
- mov cx,_spec_len >> 2
- xor eax,eax
- rep stosd
-
- ; Initialize length field of the various packets
- mov byte [spec_packet],13h
- mov byte [drive_params],30
- mov byte [dapa],16
- mov byte [dspec_packet],13h
-
- ; Other nonzero fields
- inc word [dsp_sectors]
-
- ; Now figure out what we're actually doing
- ; Note: use passed-in DL value rather than 7Fh because
- ; at least some BIOSes will get the wrong value otherwise
- mov ax,4B01h ; Get disk emulation status
- mov dl,[DriveNo]
- mov si,spec_packet
- int 13h
- jc award_hack ; changed for BrokenAwardHack
- mov dl,[DriveNo]
- cmp [sp_drive],dl ; Should contain the drive number
- jne spec_query_failed
-
- %ifdef DEBUG_MESSAGES
- mov si,spec_ok_msg
- call writemsg
- mov al,byte [sp_drive]
- call writehex2
- call crlf
- %endif
-
- found_drive:
- ; Alright, we have found the drive. Now, try to find the
- ; boot file itself. If we have a boot info table, life is
- ; good; if not, we have to make some assumptions, and try
- ; to figure things out ourselves. In particular, the
- ; assumptions we have to make are:
- ; - single session only
- ; - only one boot entry (no menu or other alternatives)
-
- cmp dword [bi_file],0 ; Address of code to load
- jne found_file ; Boot info table present :)
-
- %ifdef DEBUG_MESSAGES
- mov si,noinfotable_msg
- call writemsg
- %endif
-
- ; No such luck. See if the the spec packet contained one.
- mov eax,[sp_lba]
- and eax,eax
- jz set_file ; Good enough
-
- %ifdef DEBUG_MESSAGES
- mov si,noinfoinspec_msg
- call writemsg
- %endif
-
- ; No such luck. Get the Boot Record Volume, assuming single
- ; session disk, and that we're the first entry in the chain
- mov eax,17 ; Assumed address of BRV
- mov bx,trackbuf
- call getonesec
-
- mov eax,[trackbuf+47h] ; Get boot catalog address
- mov bx,trackbuf
- call getonesec ; Get boot catalog
-
- mov eax,[trackbuf+28h] ; First boot entry
- ; And hope and pray this is us...
-
- ; Some BIOSes apparently have limitations on the size
- ; that may be loaded (despite the El Torito spec being very
- ; clear on the fact that it must all be loaded.) Therefore,
- ; we load it ourselves, and *bleep* the BIOS.
-
- set_file:
- mov [bi_file],eax
-
- found_file:
- ; Set up boot file sizes
- mov eax,[bi_length]
- sub eax,SECTOR_SIZE-3
- shr eax,2 ; bytes->dwords
- mov [ImageDwords],eax ; boot file dwords
- add eax,(2047 >> 2)
- shr eax,9 ; dwords->sectors
- mov [ImageSectors],ax ; boot file sectors
-
- mov eax,[bi_file] ; Address of code to load
- inc eax ; Don't reload bootstrap code
- %ifdef DEBUG_MESSAGES
- mov si,offset_msg
- call writemsg
- call writehex8
- call crlf
- %endif
-
- ; Just in case some BIOSes have problems with
- ; segment wraparound, use the normalized address
- mov bx,((7C00h+2048) >> 4)
- mov es,bx
- xor bx,bx
- mov bp,[ImageSectors]
- %ifdef DEBUG_MESSAGES
- push ax
- mov si,size_msg
- call writemsg
- mov ax,bp
- call writehex4
- call crlf
- pop ax
- %endif
- call getlinsec
-
- push ds
- pop es
-
- %ifdef DEBUG_MESSAGES
- mov si,loaded_msg
- call writemsg
- %endif
-
- ; Verify the checksum on the loaded image.
- verify_image:
- mov si,7C00h+2048
- mov bx,es
- mov ecx,[ImageDwords]
- mov edi,[FirstSecSum] ; First sector checksum
- .loop es lodsd
- add edi,eax
- dec ecx
- jz .done
- and si,si
- jnz .loop
- ; SI wrapped around, advance ES
- add bx,1000h
- mov es,bx
- jmp short .loop
- .done: mov ax,ds
- mov es,ax
- cmp [bi_csum],edi
- je integrity_ok
-
- mov si,checkerr_msg
- call writemsg
- jmp kaboom
-
- integrity_ok:
- %ifdef DEBUG_MESSAGES
- mov si,allread_msg
- call writemsg
- %endif
- jmp all_read ; Jump to main code
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Start of BrokenAwardHack --- 10-nov-2002 Knut_Petersen@t-online.de
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- ;; There is a problem with certain versions of the AWARD BIOS ...
- ;; the boot sector will be loaded and executed correctly, but, because the
- ;; int 13 vector points to the wrong code in the BIOS, every attempt to
- ;; load the spec packet will fail. We scan for the equivalent of
- ;;
- ;; mov ax,0201h
- ;; mov bx,7c00h
- ;; mov cx,0006h
- ;; mov dx,0180h
- ;; pushf
- ;; call <direct far>
- ;;
- ;; and use <direct far> as the new vector for int 13. The code above is
- ;; used to load the boot code into ram, and there should be no reason
- ;; for anybody to change it now or in the future. There are no opcodes
- ;; that use encodings relativ to IP, so scanning is easy. If we find the
- ;; code above in the BIOS code we can be pretty sure to run on a machine
- ;; with an broken AWARD BIOS ...
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;
- %ifdef DEBUG_MESSAGES ;;
- ;;
- award_notice db "Trying BrokenAwardHack first ...",CR,LF,0 ;;
- award_not_orig db "BAH: Original Int 13 vector : ",0 ;;
- award_not_new db "BAH: Int 13 vector changed to : ",0 ;;
- award_not_succ db "BAH: SUCCESS",CR,LF,0 ;;
- award_not_fail db "BAH: FAILURE" ;;
- award_not_crlf db CR,LF,0 ;;
- ;;
- %endif ;;
- ;;
- award_oldint13 dd 0 ;;
- award_string db 0b8h,1,2,0bbh,0,7ch,0b9h,6,0,0bah,80h,1,09ch,09ah ;;
- ;;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- award_hack: mov si,spec_err_msg ; Moved to this place from
- call writemsg ; spec_query_faild
- ;
- %ifdef DEBUG_MESSAGES ;
- ;
- mov si,award_notice ; display our plan
- call writemsg ;
- mov si,award_not_orig ; display original int 13
- call writemsg ; vector
- %endif ;
- mov eax,[13h*4] ;
- mov [award_oldint13],eax ;
- ;
- %ifdef DEBUG_MESSAGES ;
- ;
- call writehex8 ;
- mov si,award_not_crlf ;
- call writestr ;
- %endif ;
- push es ; save ES
- mov ax,0f000h ; ES = BIOS Seg
- mov es,ax ;
- cld ;
- xor di,di ; start at ES:DI = f000:0
- award_loop: push di ; save DI
- mov si,award_string ; scan for award_string
- mov cx,7 ; length of award_string = 7dw
- repz cmpsw ; compare
- pop di ; restore DI
- jcxz award_found ; jmp if found
- inc di ; not found, inc di
- jno award_loop ;
- ;
- award_failed: pop es ; No, not this way :-((
- award_fail2: ;
- ;
- %ifdef DEBUG_MESSAGES ;
- ;
- mov si,award_not_fail ; display failure ...
- call writemsg ;
- %endif ;
- mov eax,[award_oldint13] ; restore the original int
- or eax,eax ; 13 vector if there is one
- jz spec_query_failed ; and try other workarounds
- mov [13h*4],eax ;
- jmp spec_query_failed ;
- ;
- award_found: mov eax,[es:di+0eh] ; load possible int 13 addr
- pop es ; restore ES
- ;
- cmp eax,[award_oldint13] ; give up if this is the
- jz award_failed ; active int 13 vector,
- mov [13h*4],eax ; otherwise change 0:13h*4
- ;
- ;
- %ifdef DEBUG_MESSAGES ;
- ;
- push eax ; display message and
- mov si,award_not_new ; new vector address
- call writemsg ;
- pop eax ;
- call writehex8 ;
- mov si,award_not_crlf ;
- call writestr ;
- %endif ;
- mov ax,4B01h ; try to read the spec packet
- mov dl,[DriveNo] ; now ... it should not fail
- mov si,spec_packet ; any longer
- int 13h ;
- jc award_fail2 ;
- ;
- %ifdef DEBUG_MESSAGES ;
- ;
- mov si,award_not_succ ; display our SUCCESS
- call writemsg ;
- %endif ;
- jmp found_drive ; and leave error recovery code
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; End of BrokenAwardHack ---- 10-nov-2002 Knut_Petersen@t-online.de
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
- ; INT 13h, AX=4B01h, DL=<passed in value> failed.
- ; Try to scan the entire 80h-FFh from the end.
-
- spec_query_failed:
-
- ; some code moved to BrokenAwardHack
-
- mov dl,0FFh
- .test_loop: pusha
- mov ax,4B01h
- mov si,spec_packet
- mov byte [si],13 ; Size of buffer
- int 13h
- popa
- jc .still_broken
-
- mov si,maybe_msg
- call writemsg
- mov al,dl
- call writehex2
- call crlf
-
- cmp byte [sp_drive],dl
- jne .maybe_broken
-
- ; Okay, good enough...
- mov si,alright_msg
- call writemsg
- mov [DriveNo],dl
- .found_drive: jmp found_drive
-
- ; Award BIOS 4.51 apparently passes garbage in sp_drive,
- ; but if this was the drive number originally passed in
- ; DL then consider it "good enough"
- .maybe_broken:
- cmp byte [DriveNo],dl
- je .found_drive
-
- .still_broken: dec dx
- cmp dl, 80h
- jnb .test_loop
-
- ; No spec packet anywhere. Some particularly pathetic
- ; BIOSes apparently don't even implement function
- ; 4B01h, so we can't query a spec packet no matter
- ; what. If we got a drive number in DL, then try to
- ; use it, and if it works, then well...
- mov dl,[DriveNo]
- cmp dl,81h ; Should be 81-FF at least
- jb fatal_error ; If not, it's hopeless
-
- ; Write a warning to indicate we're on *very* thin ice now
- mov si,nospec_msg
- call writemsg
- mov al,dl
- call writehex2
- call crlf
- mov si,trysbm_msg
- call writemsg
- jmp .found_drive ; Pray that this works...
-
- fatal_error:
- mov si,nothing_msg
- call writemsg
-
- .norge: jmp short .norge
-
- ; Information message (DS:SI) output
- ; Prefix with "isolinux: "
- ;
- writemsg: push ax
- push si
- mov si,isolinux_str
- call writestr
- pop si
- call writestr
- pop ax
- ret
-
- ;
- ; Write a character to the screen. There is a more "sophisticated"
- ; version of this in the subsequent code, so we patch the pointer
- ; when appropriate.
- ;
-
- writechr:
- jmp near writechr_simple ; 3-byte jump
-
- writechr_simple:
- pushfd
- pushad
- mov ah,0Eh
- xor bx,bx
- int 10h
- popad
- popfd
- ret
-
- ;
- ; Get one sector. Convenience entry point.
- ;
- getonesec:
- mov bp,1
- ; Fall through to getlinsec
-
- ;
- ; Get linear sectors - EBIOS LBA addressing, 2048-byte sectors.
- ;
- ; Note that we can't always do this as a single request, because at least
- ; Phoenix BIOSes has a 127-sector limit. To be on the safe side, stick
- ; to 32 sectors (64K) per request.
- ;
- ; Input:
- ; EAX - Linear sector number
- ; ES:BX - Target buffer
- ; BP - Sector count
- ;
- getlinsec:
- mov si,dapa ; Load up the DAPA
- mov [si+4],bx
- mov bx,es
- mov [si+6],bx
- mov [si+8],eax
- .loop:
- push bp ; Sectors left
- cmp bp,[MaxTransfer]
- jbe .bp_ok
- mov bp,[MaxTransfer]
- .bp_ok:
- mov [si+2],bp
- push si
- mov dl,[DriveNo]
- mov ah,42h ; Extended Read
- call xint13
- pop si
- pop bp
- movzx eax,word [si+2] ; Sectors we read
- add [si+8],eax ; Advance sector pointer
- sub bp,ax ; Sectors left
- shl ax,SECTOR_SHIFT-4 ; 2048-byte sectors -> segment
- add [si+6],ax ; Advance buffer pointer
- and bp,bp
- jnz .loop
- mov eax,[si+8] ; Next sector
- ret
-
- ; INT 13h with retry
- xint13: mov byte [RetryCount],retry_count
- .try: pushad
- int 13h
- jc .error
- add sp,byte 8*4 ; Clean up stack
- ret
- .error:
- mov [DiskError],ah ; Save error code
- popad
- mov [DiskSys],ax ; Save system call number
- dec byte [RetryCount]
- jz .real_error
- push ax
- mov al,[RetryCount]
- mov ah,[dapa+2] ; Sector transfer count
- cmp al,2 ; Only 2 attempts left
- ja .nodanger
- mov ah,1 ; Drop transfer size to 1
- jmp short .setsize
- .nodanger:
- cmp al,retry_count-2
- ja .again ; First time, just try again
- shr ah,1 ; Otherwise, try to reduce
- adc ah,0 ; the max transfer size, but not to 0
- .setsize:
- mov [MaxTransfer],ah
- mov [dapa+2],ah
- .again:
- pop ax
- jmp .try
-
- .real_error: mov si,diskerr_msg
- call writemsg
- mov al,[DiskError]
- call writehex2
- mov si,oncall_str
- call writestr
- mov ax,[DiskSys]
- call writehex4
- mov si,ondrive_str
- call writestr
- mov al,dl
- call writehex2
- call crlf
- ; Fall through to kaboom
-
- ;
- ; kaboom: write a message and bail out. Wait for a user keypress,
- ; then do a hard reboot.
- ;
- kaboom:
- lss sp,[cs:Stack]
- mov ax,cs
- mov ds,ax
- mov es,ax
- mov fs,ax
- mov gs,ax
- sti
- mov si,err_bootfailed
- call cwritestr
- call getchar
- cli
- mov word [BIOS_magic],0 ; Cold reboot
- jmp 0F000h:0FFF0h ; Reset vector address
-
- ; -----------------------------------------------------------------------------
- ; Common modules needed in the first sector
- ; -----------------------------------------------------------------------------
-
- %include "writestr.inc" ; String output
- writestr equ cwritestr
- %include "writehex.inc" ; Hexadecimal output
-
- ; -----------------------------------------------------------------------------
- ; Data that needs to be in the first sector
- ; -----------------------------------------------------------------------------
-
- syslinux_banner db CR, LF, 'ISOLINUX ', version_str, ' ', date, ' ', 0
- copyright_str db ' Copyright (C) 1994-', year, ' H. Peter Anvin'
- db CR, LF, 0
- isolinux_str db 'isolinux: ', 0
- %ifdef DEBUG_MESSAGES
- startup_msg: db 'Starting up, DL = ', 0
- spec_ok_msg: db 'Loaded spec packet OK, drive = ', 0
- secsize_msg: db 'Sector size appears to be ', 0
- offset_msg: db 'Loading main image from LBA = ', 0
- size_msg: db 'Sectors to load = ', 0
- loaded_msg: db 'Loaded boot image, verifying...', CR, LF, 0
- verify_msg: db 'Image checksum verified.', CR, LF, 0
- allread_msg db 'Main image read, jumping to main code...', CR, LF, 0
- %endif
- noinfotable_msg db 'No boot info table, assuming single session disk...', CR, LF, 0
- noinfoinspec_msg db 'Spec packet missing LBA information, trying to wing it...', CR, LF, 0
- spec_err_msg: db 'Loading spec packet failed, trying to wing it...', CR, LF, 0
- maybe_msg: db 'Found something at drive = ', 0
- alright_msg: db 'Looks like it might be right, continuing...', CR, LF, 0
- nospec_msg db 'Extremely broken BIOS detected, last ditch attempt with drive = ', 0
- nothing_msg: db 'Failed to locate CD-ROM device; boot failed.', CR, LF
- trysbm_msg db 'See http://syslinux.zytor.com/sbm for more information.', CR, LF, 0
- diskerr_msg: db 'Disk error ', 0
- oncall_str: db ', AX = ',0
- ondrive_str: db ', drive ', 0
- checkerr_msg: db 'Image checksum error, sorry...', CR, LF, 0
-
- err_bootfailed db CR, LF, 'Boot failed: press a key to retry...'
- bailmsg equ err_bootfailed
- crlf_msg db CR, LF
- null_msg db 0
-
- alignb 4, db 0
- Stack dw _start, 0 ; SS:SP for stack reset
- MaxTransfer dw 32 ; Max sectors per transfer
-
- rl_checkpt equ $ ; Must be <= 800h
-
- rl_checkpt_off equ ($-$$)
- ;%ifndef DEPEND
- ;%if rl_checkpt_off > 0x800
- ;%error "Sector 0 overflow"
- ;%endif
- ;%endif
-
- ; ----------------------------------------------------------------------------
- ; End of code and data that have to be in the first sector
- ; ----------------------------------------------------------------------------
-
- all_read:
- ;
- ; Initialize screen (if we're using one)
- ;
- ; Now set up screen parameters
- call adjust_screen
-
- ; Wipe the F-key area
- mov al,NULLFILE
- mov di,FKeyName
- mov cx,10*(1 << FILENAME_MAX_LG2)
- rep stosb
-
- ; Patch the writechr routine to point to the full code
- mov word [writechr+1], writechr_full-(writechr+3)
-
- ; Tell the user we got this far...
- %ifndef DEBUG_MESSAGES ; Gets messy with debugging on
- mov si,copyright_str
- call writestr
- %endif
-
- ; Test tracers
- TRACER 'T'
- TRACER '>'
-
- ;
- ; Common initialization code
- ;
- %include "init.inc"
- %include "cpuinit.inc"
-
- ;
- ; Now we're all set to start with our *real* business. First load the
- ; configuration file (if any) and parse it.
- ;
- ; In previous versions I avoided using 32-bit registers because of a
- ; rumour some BIOSes clobbered the upper half of 32-bit registers at
- ; random. I figure, though, that if there are any of those still left
- ; they probably won't be trying to install Linux on them...
- ;
- ; The code is still ripe with 16-bitisms, though. Not worth the hassle
- ; to take'm out. In fact, we may want to put them back if we're going
- ; to boot ELKS at some point.
- ;
-
- ;
- ; Now, we need to sniff out the actual filesystem data structures.
- ; mkisofs gave us a pointer to the primary volume descriptor
- ; (which will be at 16 only for a single-session disk!); from the PVD
- ; we should be able to find the rest of what we need to know.
- ;
- get_fs_structures:
- mov eax,[bi_pvd]
- mov bx,trackbuf
- call getonesec
-
- mov eax,[trackbuf+156+2]
- mov [RootDir+dir_lba],eax
- mov [CurDir+dir_lba],eax
- %ifdef DEBUG_MESSAGES
- mov si,dbg_rootdir_msg
- call writemsg
- call writehex8
- call crlf
- %endif
- mov eax,[trackbuf+156+10]
- mov [RootDir+dir_len],eax
- mov [CurDir+dir_len],eax
- add eax,SECTOR_SIZE-1
- shr eax,SECTOR_SHIFT
- mov [RootDir+dir_clust],eax
- mov [CurDir+dir_clust],eax
-
- ; Look for an isolinux directory, and if found,
- ; make it the current directory instead of the root
- ; directory.
- mov di,boot_dir ; Search for /boot/isolinux
- mov al,02h
- call searchdir_iso
- jnz .found_dir
- mov di,isolinux_dir
- mov al,02h ; Search for /isolinux
- call searchdir_iso
- jz .no_isolinux_dir
- .found_dir:
- mov [CurDir+dir_len],eax
- mov eax,[si+file_left]
- mov [CurDir+dir_clust],eax
- xor eax,eax ; Free this file pointer entry
- xchg eax,[si+file_sector]
- mov [CurDir+dir_lba],eax
- %ifdef DEBUG_MESSAGES
- push si
- mov si,dbg_isodir_msg
- call writemsg
- pop si
- call writehex8
- call crlf
- %endif
- .no_isolinux_dir:
-
- ;
- ; Locate the configuration file
- ;
- load_config:
- %ifdef DEBUG_MESSAGES
- mov si,dbg_config_msg
- call writemsg
- %endif
-
- mov di,isolinux_cfg
- call open
- jz no_config_file ; Not found or empty
-
- %ifdef DEBUG_MESSAGES
- mov si,dbg_configok_msg
- call writemsg
- %endif
-
- ;
- ; Now we have the config file open. Parse the config file and
- ; run the user interface.
- ;
- %include "ui.inc"
-
- ;
- ; Linux kernel loading code is common.
- ;
- %include "runkernel.inc"
-
- ;
- ; COMBOOT-loading code
- ;
- %include "comboot.inc"
- %include "com32.inc"
- %include "cmdline.inc"
-
- ;
- ; Boot sector loading code
- ;
- %include "bootsect.inc"
-
- ;
- ; Enable disk emulation. The kind of disk we emulate is dependent on the size of
- ; the file: 1200K, 1440K or 2880K floppy, otherwise harddisk.
- ;
- is_disk_image:
- TRACER CR
- TRACER LF
- TRACER 'D'
- TRACER ':'
-
- shl edx,16
- mov dx,ax ; Set EDX <- file size
- mov di,img_table
- mov cx,img_table_count
- mov eax,[si+file_sector] ; Starting LBA of file
- mov [dsp_lba],eax ; Location of file
- mov byte [dsp_drive], 0 ; 00h floppy, 80h hard disk
- .search_table:
- TRACER 't'
- mov eax,[di+4]
- cmp edx,[di]
- je .type_found
- add di,8
- loop .search_table
-
- ; Hard disk image. Need to examine the partition table
- ; in order to deduce the C/H/S geometry. Sigh.
- .hard_disk_image:
- TRACER 'h'
- cmp edx,512
- jb .bad_image
-
- mov bx,trackbuf
- mov cx,1 ; Load 1 sector
- call getfssec
-
- cmp word [trackbuf+510],0aa55h ; Boot signature
- jne .bad_image ; Image not bootable
-
- mov cx,4 ; 4 partition entries
- mov di,trackbuf+446 ; Start of partition table
-
- xor ax,ax ; Highest sector(al) head(ah)
-
- .part_scan:
- cmp byte [di+4], 0
- jz .part_loop
- lea si,[di+1]
- call .hs_check
- add si,byte 4
- call .hs_check
- .part_loop:
- add di,byte 16
- loop .part_scan
-
- push eax ; H/S
- push edx ; File size
- mov bl,ah
- xor bh,bh
- inc bx ; # of heads in BX
- xor ah,ah ; # of sectors in AX
- cwde ; EAX[31:16] <- 0
- mul bx
- shl eax,9 ; Convert to bytes
- ; Now eax contains the number of bytes per cylinder
- pop ebx ; File size
- xor edx,edx
- div ebx
- and edx,edx
- jz .no_remainder
- inc eax ; Fractional cylinder...
- ; Now (e)ax contains the number of cylinders
- .no_remainder: cmp eax,1024
- jna .ok_cyl
- mov ax,1024 ; Max possible #
- .ok_cyl: dec ax ; Convert to max cylinder no
- pop ebx ; S(bl) H(bh)
- shl ah,6
- or bl,ah
- xchg ax,bx
- shl eax,16
- mov ah,bl
- mov al,4 ; Hard disk boot
- mov byte [dsp_drive], 80h ; Drive 80h = hard disk
-
- .type_found:
- TRACER 'T'
- mov bl,[sp_media]
- and bl,0F0h ; Copy controller info bits
- or al,bl
- mov [dsp_media],al ; Emulation type
- shr eax,8
- mov [dsp_chs],eax ; C/H/S geometry
- mov ax,[sp_devspec] ; Copy device spec
- mov [dsp_devspec],ax
- mov al,[sp_controller] ; Copy controller index
- mov [dsp_controller],al
-
- TRACER 'V'
- call vgaclearmode ; Reset video
-
- mov ax,4C00h ; Enable emulation and boot
- mov si,dspec_packet
- mov dl,[DriveNo]
- lss sp,[InitStack]
- TRACER 'X'
-
- int 13h
-
- ; If this returns, we have problems
- .bad_image:
- mov si,err_disk_image
- call cwritestr
- jmp enter_command
-
- ;
- ; Look for the highest seen H/S geometry
- ; We compute cylinders separately
- ;
- .hs_check:
- mov bl,[si] ; Head #
- cmp bl,ah
- jna .done_track
- mov ah,bl ; New highest head #
- .done_track: mov bl,[si+1]
- and bl,3Fh ; Sector #
- cmp bl,al
- jna .done_sector
- mov al,bl
- .done_sector: ret
-
- ;
- ; Boot a specified local disk. AX specifies the BIOS disk number; or
- ; 0xFFFF in case we should execute INT 18h ("next device.")
- ;
- local_boot:
- call vgaclearmode
- lss sp,[cs:Stack] ; Restore stack pointer
- xor dx,dx
- mov ds,dx
- mov es,dx
- mov fs,dx
- mov gs,dx
- mov si,localboot_msg
- call writestr
- cmp ax,-1
- je .int18
-
- ; Load boot sector from the specified BIOS device and jump to it.
- mov dl,al
- xor dh,dh
- push dx
- xor ax,ax ; Reset drive
- call xint13
- mov ax,0201h ; Read one sector
- mov cx,0001h ; C/H/S = 0/0/1 (first sector)
- mov bx,trackbuf
- call xint13
- pop dx
- cli ; Abandon hope, ye who enter here
- mov si,trackbuf
- mov di,07C00h
- mov cx,512 ; Probably overkill, but should be safe
- rep movsd
- lss sp,[cs:InitStack]
- jmp 0:07C00h ; Jump to new boot sector
-
- .int18:
- int 18h ; Hope this does the right thing...
- jmp kaboom ; If we returned, oh boy...
-
- ;
- ; abort_check: let the user abort with <ESC> or <Ctrl-C>
- ;
- abort_check:
- call pollchar
- jz ac_ret1
- pusha
- call getchar
- cmp al,27 ; <ESC>
- je ac_kill
- cmp al,3 ; <Ctrl-C>
- jne ac_ret2
- ac_kill: mov si,aborted_msg
-
- ;
- ; abort_load: Called by various routines which wants to print a fatal
- ; error message and return to the command prompt. Since this
- ; may happen at just about any stage of the boot process, assume
- ; our state is messed up, and just reset the segment registers
- ; and the stack forcibly.
- ;
- ; SI = offset (in _text) of error message to print
- ;
- abort_load:
- mov ax,cs ; Restore CS = DS = ES
- mov ds,ax
- mov es,ax
- cli
- lss sp,[cs:Stack] ; Reset the stack
- sti
- call cwritestr ; Expects SI -> error msg
- al_ok: jmp enter_command ; Return to command prompt
- ;
- ; End of abort_check
- ;
- ac_ret2: popa
- ac_ret1: ret
-
-
- ;
- ; searchdir:
- ;
- ; Open a file
- ;
- ; On entry:
- ; DS:DI = filename
- ; If successful:
- ; ZF clear
- ; SI = file pointer
- ; DX:AX or EAX = file length in bytes
- ; If unsuccessful
- ; ZF set
- ;
-
- ;
- ; searchdir_iso is a special entry point for ISOLINUX only. In addition
- ; to the above, searchdir_iso passes a file flag mask in AL. This is useful
- ; for searching for directories.
- ;
- alloc_failure:
- xor ax,ax ; ZF <- 1
- ret
-
- searchdir:
- xor al,al
- searchdir_iso:
- mov [ISOFlags],al
- TRACER 'S'
- call allocate_file ; Temporary file structure for directory
- jnz alloc_failure
- push es
- push ds
- pop es ; ES = DS
- mov si,CurDir
- cmp byte [di],'/' ; If filename begins with slash
- jne .not_rooted
- inc di ; Skip leading slash
- mov si,RootDir ; Reference root directory instead
- .not_rooted:
- mov eax,[si+dir_clust]
- mov [bx+file_left],eax
- mov eax,[si+dir_lba]
- mov [bx+file_sector],eax
- mov edx,[si+dir_len]
-
- .look_for_slash:
- mov ax,di
- .scan:
- mov cl,[di]
- inc di
- and cl,cl
- jz .isfile
- cmp cl,'/'
- jne .scan
- mov [di-1],byte 0 ; Terminate at directory name
- mov cl,02h ; Search for directory
- xchg cl,[ISOFlags]
-
- push di ; Save these...
- push cx
-
- ; Create recursion stack frame...
- push word .resume ; Where to "return" to
- push es
- .isfile: xchg ax,di
-
- .getsome:
- ; Get a chunk of the directory
- ; This relies on the fact that ISOLINUX doesn't change SI
- mov si,trackbuf
- TRACER 'g'
- pushad
- xchg bx,si
- mov cx,[BufSafe]
- call getfssec
- popad
-
- .compare:
- movzx eax,byte [si] ; Length of directory entry
- cmp al,33
- jb .next_sector
- TRACER 'c'
- mov cl,[si+25]
- xor cl,[ISOFlags]
- test cl, byte 8Eh ; Unwanted file attributes!
- jnz .not_file
- pusha
- movzx cx,byte [si+32] ; File identifier length
- add si,byte 33 ; File identifier offset
- TRACER 'i'
- call iso_compare_names
- popa
- je .success
- .not_file:
- sub edx,eax ; Decrease bytes left
- jbe .failure
- add si,ax ; Advance pointer
-
- .check_overrun:
- ; Did we finish the buffer?
- cmp si,trackbuf+trackbufsize
- jb .compare ; No, keep going
-
- jmp short .getsome ; Get some more directory
-
- .next_sector:
- ; Advance to the beginning of next sector
- lea ax,[si+SECTOR_SIZE-1]
- and ax,~(SECTOR_SIZE-1)
- sub ax,si
- jmp short .not_file ; We still need to do length checks
-
- .failure: xor eax,eax ; ZF = 1
- mov [bx+file_sector],eax
- pop es
- ret
-
- .success:
- mov eax,[si+2] ; Location of extent
- mov [bx+file_sector],eax
- mov eax,[si+10] ; Data length
- push eax
- add eax,SECTOR_SIZE-1
- shr eax,SECTOR_SHIFT
- mov [bx+file_left],eax
- pop eax
- mov edx,eax
- shr edx,16
- and bx,bx ; ZF = 0
- mov si,bx
- pop es
- ret
-
- .resume: ; We get here if we were only doing part of a lookup
- ; This relies on the fact that .success returns bx == si
- xchg edx,eax ; Directory length in edx
- pop cx ; Old ISOFlags
- pop di ; Next filename pointer
- mov byte [di-1], '/' ; Restore slash
- mov [ISOFlags],cl ; Restore the flags
- jz .failure ; Did we fail? If so fail for real!
- jmp .look_for_slash ; Otherwise, next level
-
- ;
- ; allocate_file: Allocate a file structure
- ;
- ; If successful:
- ; ZF set
- ; BX = file pointer
- ; In unsuccessful:
- ; ZF clear
- ;
- allocate_file:
- TRACER 'a'
- push cx
- mov bx,Files
- mov cx,MAX_OPEN
- .check: cmp dword [bx], byte 0
- je .found
- add bx,open_file_t_size ; ZF = 0
- loop .check
- ; ZF = 0 if we fell out of the loop
- .found: pop cx
- ret
-
- ;
- ; iso_compare_names:
- ; Compare the names DS:SI and DS:DI and report if they are
- ; equal from an ISO 9660 perspective. SI is the name from
- ; the filesystem; CX indicates its length, and ';' terminates.
- ; DI is expected to end with a null.
- ;
- ; Note: clobbers AX, CX, SI, DI; assumes DS == ES == base segment
- ;
-
- iso_compare_names:
- ; First, terminate and canonicalize input filename
- push di
- mov di,ISOFileName
- .canon_loop: jcxz .canon_end
- lodsb
- dec cx
- cmp al,';'
- je .canon_end
- and al,al
- je .canon_end
- stosb
- cmp di,ISOFileNameEnd-1 ; Guard against buffer overrun
- jb .canon_loop
- .canon_end:
- cmp di,ISOFileName
- jbe .canon_done
- cmp byte [di-1],'.' ; Remove terminal dots
- jne .canon_done
- dec di
- jmp short .canon_end
- .canon_done:
- mov [di],byte 0 ; Null-terminate string
- pop di
- mov si,ISOFileName
- .compare:
- lodsb
- mov ah,[di]
- inc di
- and ax,ax
- jz .success ; End of string for both
- and al,al ; Is either one end of string?
- jz .failure ; If so, failure
- and ah,ah
- jz .failure
- or ax,2020h ; Convert to lower case
- cmp al,ah
- je .compare
- .failure: and ax,ax ; ZF = 0 (at least one will be nonzero)
- .success: ret
-
- ;
- ; mangle_name: Mangle a filename pointed to by DS:SI into a buffer pointed
- ; to by ES:DI; ends on encountering any whitespace.
- ;
- ; This verifies that a filename is < FILENAME_MAX characters,
- ; doesn't contain whitespace, zero-pads the output buffer,
- ; and removes trailing dots and redundant slashes,
- ; so "repe cmpsb" can do a compare, and the
- ; path-searching routine gets a bit of an easier job.
- ;
- mangle_name:
- push bx
- xor ax,ax
- mov cx,FILENAME_MAX-1
- mov bx,di
-
- .mn_loop:
- lodsb
- cmp al,' ' ; If control or space, end
- jna .mn_end
- cmp al,ah ; Repeated slash?
- je .mn_skip
- xor ah,ah
- cmp al,'/'
- jne .mn_ok
- mov ah,al
- .mn_ok stosb
- .mn_skip: loop .mn_loop
- .mn_end:
- cmp bx,di ; At the beginning of the buffer?
- jbe .mn_zero
- cmp byte [di-1],'.' ; Terminal dot?
- je .mn_kill
- cmp byte [di-1],'/' ; Terminal slash?
- jne .mn_zero
- .mn_kill: dec di ; If so, remove it
- inc cx
- jmp short .mn_end
- .mn_zero:
- inc cx ; At least one null byte
- xor ax,ax ; Zero-fill name
- rep stosb
- pop bx
- ret ; Done
-
- ;
- ; unmangle_name: Does the opposite of mangle_name; converts a DOS-mangled
- ; filename to the conventional representation. This is needed
- ; for the BOOT_IMAGE= parameter for the kernel.
- ; NOTE: A 13-byte buffer is mandatory, even if the string is
- ; known to be shorter.
- ;
- ; DS:SI -> input mangled file name
- ; ES:DI -> output buffer
- ;
- ; On return, DI points to the first byte after the output name,
- ; which is set to a null byte.
- ;
- unmangle_name: call strcpy
- dec di ; Point to final null byte
- ret
-
- ;
- ; getfssec: Get multiple clusters from a file, given the file pointer.
- ;
- ; On entry:
- ; ES:BX -> Buffer
- ; SI -> File pointer
- ; CX -> Cluster count
- ; On exit:
- ; SI -> File pointer (or 0 on EOF)
- ; CF = 1 -> Hit EOF
- ;
- getfssec:
- TRACER 'F'
-
- push ds
- push cs
- pop ds ; DS <- CS
-
- movzx ecx,cx
- cmp ecx,[si+file_left]
- jna .ok_size
- mov ecx,[si+file_left]
- .ok_size:
-
- mov bp,cx
- push cx
- push si
- mov eax,[si+file_sector]
- TRACER 'l'
- call getlinsec
- xor ecx,ecx
- pop si
- pop cx
-
- add [si+file_sector],ecx
- sub [si+file_left],ecx
- ja .not_eof ; CF = 0
-
- xor ecx,ecx
- mov [si+file_sector],ecx ; Mark as unused
- xor si,si
- stc
-
- .not_eof:
- pop ds
- TRACER 'f'
- ret
-
- ; -----------------------------------------------------------------------------
- ; Common modules
- ; -----------------------------------------------------------------------------
-
- %include "getc.inc" ; getc et al
- %include "conio.inc" ; Console I/O
- %include "parseconfig.inc" ; High-level config file handling
- %include "parsecmd.inc" ; Low-level config file handling
- %include "bcopy32.inc" ; 32-bit bcopy
- %include "loadhigh.inc" ; Load a file into high memory
- %include "font.inc" ; VGA font stuff
- %include "graphics.inc" ; VGA graphics
- %include "highmem.inc" ; High memory sizing
- %include "strcpy.inc" ; strcpy()
- %include "rawcon.inc" ; Console I/O w/o using the console functions
-
- ; -----------------------------------------------------------------------------
- ; Begin data section
- ; -----------------------------------------------------------------------------
-
- section .data
-
- boot_prompt db 'boot: ', 0
- wipe_char db BS, ' ', BS, 0
- err_notfound db 'Could not find kernel image: ',0
- err_notkernel db CR, LF, 'Invalid or corrupt kernel image.', CR, LF, 0
- err_noram db 'It appears your computer has less than '
- asciidec dosram_k
- db 'K of low ("DOS")'
- db CR, LF
- db 'RAM. Linux needs at least this amount to boot. If you get'
- db CR, LF
- db 'this message in error, hold down the Ctrl key while'
- db CR, LF
- db 'booting, and I will take your word for it.', CR, LF, 0
- err_badcfg db 'Unknown keyword in config file.', CR, LF, 0
- err_noparm db 'Missing parameter in config file.', CR, LF, 0
- err_noinitrd db CR, LF, 'Could not find ramdisk image: ', 0
- err_nohighmem db 'Not enough memory to load specified kernel.', CR, LF, 0
- err_highload db CR, LF, 'Kernel transfer failure.', CR, LF, 0
- err_oldkernel db 'Cannot load a ramdisk with an old kernel image.'
- db CR, LF, 0
- err_notdos db ': attempted DOS system call', CR, LF, 0
- err_comlarge db 'COMBOOT image too large.', CR, LF, 0
- err_bssimage db 'BSS images not supported.', CR, LF, 0
- err_a20 db CR, LF, 'A20 gate not responding!', CR, LF, 0
- notfound_msg db 'not found', CR, LF, 0
- localboot_msg db 'Booting from local disk...', CR, LF, 0
- cmdline_msg db 'Command line: ', CR, LF, 0
- ready_msg db 'Ready.', CR, LF, 0
- trying_msg db 'Trying to load: ', 0
- crlfloading_msg db CR, LF ; Fall through
- loading_msg db 'Loading ', 0
- dotdot_msg db '.'
- dot_msg db '.', 0
- fourbs_msg db BS, BS, BS, BS, 0
- aborted_msg db ' aborted.', CR, LF, 0
- crff_msg db CR, FF, 0
- default_str db 'default', 0
- default_len equ ($-default_str)
- boot_dir db '/boot' ; /boot/isolinux
- isolinux_dir db '/isolinux', 0
- ConfigName equ $
- isolinux_cfg db 'isolinux.cfg', 0
- err_disk_image db 'Cannot load disk image (invalid file)?', CR, LF, 0
-
- %ifdef DEBUG_MESSAGES
- dbg_rootdir_msg db 'Root directory at LBA = ', 0
- dbg_isodir_msg db 'isolinux directory at LBA = ', 0
- dbg_config_msg db 'About to load config file...', CR, LF, 0
- dbg_configok_msg db 'Configuration file opened...', CR, LF, 0
- %endif
- ;
- ; Command line options we'd like to take a look at
- ;
- ; mem= and vga= are handled as normal 32-bit integer values
- initrd_cmd db 'initrd='
- initrd_cmd_len equ 7
-
- ;
- ; Config file keyword table
- ;
- %include "keywords.inc"
-
- ;
- ; Extensions to search for (in *forward* order).
- ;
- align 4, db 0
- exten_table: db '.cbt' ; COMBOOT (specific)
- db '.img' ; Disk image
- db '.bin' ; CD boot sector
- db '.com' ; COMBOOT (same as DOS)
- db '.c32' ; COM32
- exten_table_end:
- dd 0, 0 ; Need 8 null bytes here
-
- ;
- ; Floppy image table
- ;
- align 4, db 0
- img_table_count equ 3
- img_table:
- dd 1200*1024 ; 1200K floppy
- db 1 ; Emulation type
- db 80-1 ; Max cylinder
- db 15 ; Max sector
- db 2-1 ; Max head
-
- dd 1440*1024 ; 1440K floppy
- db 2 ; Emulation type
- db 80-1 ; Max cylinder
- db 18 ; Max sector
- db 2-1 ; Max head
-
- dd 2880*1024 ; 2880K floppy
- db 3 ; Emulation type
- db 80-1 ; Max cylinder
- db 36 ; Max sector
- db 2-1 ; Max head
-
- ;
- ; Misc initialized (data) variables
- ;
-
- ;
- ; Variables that are uninitialized in SYSLINUX but initialized here
- ;
- ; **** ISOLINUX:: We may have to make this flexible, based on what the
- ; **** BIOS expects our "sector size" to be.
- ;
- alignb 4, db 0
- BufSafe dw trackbufsize/SECTOR_SIZE ; Clusters we can load into trackbuf
- BufSafeSec dw trackbufsize/SECTOR_SIZE ; = how many sectors?
- BufSafeBytes dw trackbufsize ; = how many bytes?
- EndOfGetCBuf dw getcbuf+trackbufsize ; = getcbuf+BufSafeBytes
- %ifndef DEPEND
- %if ( trackbufsize % SECTOR_SIZE ) != 0
- %error trackbufsize must be a multiple of SECTOR_SIZE
- %endif
- %endif
-